/*
 * Copyright (C) 2014 Realtek Semiconductor Corp.
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated,
 * modified or distributed under the authorized license from Realtek.
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
 *
 * Purpose : Definition of ME handler: ont self loop detect (244)
 *
 * Feature : The file includes the following modules and sub-modules
 *           (1) ME handler: ont self loop detect (244)
 */

#include "app_basic.h"
#ifdef KAON_PLATFORM
#include "rt_acl_ext.h"
#endif

MIB_TABLE_INFO_T gMibOntSelfLoopDetectTableInfo;
MIB_ATTR_INFO_T  gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ATTR_NUM];
MIB_TABLE_ONTSELFLOOPDETECT_T gMibOntSelfLoopDetectDefRow;
MIB_TABLE_OPER_T gMibOntSelfLoopDetectOper;

#ifdef KAON_PLATFORM
const char FC_LOOP_DETECTION_ACL_INDEX_FILE[] = "/var/fc_loop_detection_acl_index_file";
enum acl_weight{
    WEIGHT_LOW      = 1,        //lowest priority
    WEIGHT_QOS_LOW  = 200,
    WEIGHT_NORMAL   = 250,
    WEIGHT_HW_VLAN_FILTER_LOW   = 300,
    WEIGHT_HW_VLAN_FILTER_MED   = 400,
    WEIGHT_HW_VLAN_FILTER_HIGH  = 500,
    WEIGHT_QOS_HIGH = WEIGHT_HW_VLAN_FILTER_HIGH + 50,
    WEIGHT_LOOP_DETECT_HIGH = 65000,
    WEIGHT_HIGH     = 65535,    //highest priority
};

static int read_pid(const char *filename)
{
    FILE *fp = NULL;
    int pid = 0;

    if((fp = fopen(filename, "r")) == NULL)
        return -1;

    if(fscanf(fp, "%d", &pid) != 1 || kill(pid, 0) != 0)
        pid = 0;

    fclose(fp);
    return pid;
}

static int kaon_fc_loop_detection_acl_flush()
{
    FILE *fp = NULL;
    int acl_idx = 0, ret = 0;

    if(!(fp = fopen(FC_LOOP_DETECTION_ACL_INDEX_FILE, "r")))
        return -2;

    while(fscanf(fp, "%d\n", &acl_idx) != EOF)
    {
        if((ret = rt_acl_filterAndQos_del(acl_idx)) != RT_ERR_OK)
            OMCI_LOG(OMCI_LOG_LEVEL_ERR, "[%s@%d] rt_acl_filterAndQos_del failed! idx = %d (ret = %d)\n", __FUNCTION__, __LINE__, acl_idx, ret);
    }

    fclose(fp);
    unlink(FC_LOOP_DETECTION_ACL_INDEX_FILE);

    return 0;
}

static int kaon_fc_loop_detection_acl_set()
{
    rt_acl_filterAndQos_t aclRule;
    uint32 acl_idx=0;
    int32 ret=0;
    FILE *fp=NULL;
    unsigned short ether_type=0xfffa;

    if(!(fp = fopen(FC_LOOP_DETECTION_ACL_INDEX_FILE, "a")))
    {
        OMCI_LOG(OMCI_LOG_LEVEL_ERR, "ERROR! %s\n", strerror(errno));
        return -2;
    }

    memset(&aclRule, 0, sizeof(rt_acl_filterAndQos_t));
    aclRule.acl_weight = WEIGHT_LOOP_DETECT_HIGH;
    aclRule.filter_fields |= RT_ACL_INGRESS_PORT_MASK_BIT;
    //include all lan port
    aclRule.ingress_port_mask = 15;
    aclRule.filter_fields |= RT_ACL_INGRESS_ETHERTYPE_BIT;
    aclRule.ingress_ethertype = ether_type;
    aclRule.ingress_ethertype_mask = 0xffff;
    aclRule.action_fields = (RT_ACL_ACTION_FORWARD_GROUP_TRAP_BIT|RT_ACL_ACTION_PRIORITY_GROUP_TRAP_PRIORITY_BIT);
    aclRule.action_priority_group_trap_priority = 7;
    if((ret = rt_acl_filterAndQos_add(aclRule, &acl_idx)) == RT_ERR_OK)
    {
        OMCI_LOG(OMCI_LOG_LEVEL_ERR,"%d\n", acl_idx);
        fclose(fp);
        return 0;
    } 
    else
    {
        OMCI_LOG(OMCI_LOG_LEVEL_ERR,"[%s@%d] rt_acl_filterAndQos_add failed! (ret = %d)\n",__FUNCTION__,__LINE__, ret);
        fclose(fp);
        return -1;
    }
}

static void kaon_setupLBD()
{
    char cmd[256] = {0};
    char enable[4] = {0};
    int pid = 0, i = 0;

    memset(cmd, 0, sizeof(cmd));
    snprintf(cmd, sizeof(cmd), "echo \"0 1 2 3\" > /proc/sys/loopback_detect/lan_port_remapping");
    system(cmd);

    for(i = 0; i < 4; i++)
    {
        memset(cmd, 0, sizeof(cmd));
        snprintf(cmd, sizeof(cmd), "/bin/smuxctl --if eth0.%d --rx --tags 1 --rule-remove-alias eth0.%d-rx-loopdetect+", (i+2), (i+2));
        system(cmd);
    }

    omci_get_boa_mib_value_by_name("LBD_ENABLE",enable);

    if(1 == atoi(enable))
    {
        kaon_fc_loop_detection_acl_flush();
        kaon_fc_loop_detection_acl_set();

        memset(cmd, 0, sizeof(cmd));
        snprintf(cmd, sizeof(cmd), "echo 0xfffa > /proc/loopback_detect_ethtype");
        system(cmd);
    }

    pid = read_pid("/var/run/loopback.pid");
    if(pid > 0)
    {
        kill(pid, SIGTERM);
        while(read_pid("/var/run/loopback.pid") > 0)
            usleep(200);
    }

    if(1 == atoi(enable))
        system("/bin/loopback &");
    else
        system("echo stop > /proc/loopback_detect");
}
#endif
GOS_ERROR_CODE OntSelfLoopDetectCfg(void            *pOldRow,
                                    void            *pNewRow,
                                    MIB_OPERA_TYPE  operationType,
                                    MIB_ATTRS_SET   attrSet,
                                    UINT32          pri)
{
    GOS_ERROR_CODE                      ret = GOS_OK;
    //BOOL                                bWrite = FALSE;
    MIB_TABLE_ONTSELFLOOPDETECT_T       *pNewMib = NULL;
    MIB_TABLE_ONTSELFLOOPDETECT_T       *pOldMib = NULL;
    MIB_TABLE_INDEX                     tableIndex = MIB_TABLE_ONT_SELFLOOPDETECT_INDEX;
#ifdef KAON_PLATFORM
    char cmd[256] = {0};
#endif

    pNewMib = (MIB_TABLE_ONTSELFLOOPDETECT_T *)pNewRow;
    pOldMib = (MIB_TABLE_ONTSELFLOOPDETECT_T *)pOldRow;


	switch (operationType)
	{
		case MIB_ADD:
            ret = mib_alarm_table_add(tableIndex, pNewRow);
            break;
        case MIB_DEL:
            ret = mib_alarm_table_del(tableIndex, pOldRow);
            break;
        case MIB_SET:
            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX) &&
                pNewMib->EnableLoopDetect != pOldMib->EnableLoopDetect)
            {
#ifdef KAON_PLATFORM
                memset(cmd, 0, sizeof(cmd));
                snprintf(cmd, sizeof(cmd), "mib set LBD_ENABLE %u", pNewMib->EnableLoopDetect);
                system(cmd);
#else
                /* change disable to enable */
                if (pNewMib->EnableLoopDetect)
                {
                    // TBD
                }

                /* change enable to disable */
                if (!pNewMib->EnableLoopDetect)
                {
                    // TBD
                }
#endif
            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX) &&
                pNewMib->DetectAction != pOldMib->DetectAction)
            {
                // TBD
            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX) &&
                pNewMib->SendingPeriod != pOldMib->SendingPeriod)
            {
#ifdef KAON_PLATFORM
                memset(cmd, 0, sizeof(cmd));
                snprintf(cmd, sizeof(cmd), "mib set LBD_EXIST_PERIOD %u", pNewMib->SendingPeriod);
                system(cmd);
#endif
            }

#ifdef KAON_PLATFORM
            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX) &&
                pNewMib->BlockTimer != pOldMib->BlockTimer)
            {
                memset(cmd, 0, sizeof(cmd));
                snprintf(cmd, sizeof(cmd), "mib set LBD_CANCEL_PERIOD %u", pNewMib->BlockTimer);
                system(cmd);
            }

            memset(cmd, 0, sizeof(cmd));
            snprintf(cmd, sizeof(cmd), "mib commit");
            system(cmd);

            kaon_setupLBD();
#endif

            break;

        case MIB_GET:
            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX))
			{
			    //bWrite = TRUE;
			}

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX))
            {
                //bWrite = TRUE;
            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX))
            {
                //bWrite = TRUE;
            }

            /*if (bWrite)
                MIB_Set(tableIndex, pNewMib, sizeof(MIB_TABLE_ONTSELFLOOPDETECT_T));*/
            break;
		default:
            break;
	}

#ifndef KAON_PLATFORM
    {
        MIB_TABLE_ONTSELFLOOPDETECT_T mibSelfLoopDetect;

        mibSelfLoopDetect.EntityID = instanceID;

    }
#endif

	return ret;
}

static GOS_ERROR_CODE ont_self_loop_detect_avc_cb(MIB_TABLE_INDEX   tableIndex,
                                                    void            *pOldRow,
                                                    void            *pNewRow,
                                                    MIB_ATTRS_SET   *pAttrsSet,
                                                    MIB_OPERA_TYPE  operationType)
{

    MIB_ATTR_INDEX      attrIndex;
    UINT32              i;
    MIB_ATTRS_SET       avcAttrSet;
    BOOL                isSuppressed;

    if (MIB_SET != operationType && MIB_ADD != operationType)
        return GOS_OK;

    if (!pNewRow || !pAttrsSet)
        return GOS_ERR_PARAM;


    // check if notifications are suppressed
    omci_is_notify_suppressed_by_circuitpack(0x00, &isSuppressed);

    if (isSuppressed)
        MIB_ClearAttrSet(&avcAttrSet);
    else
    {
        avcAttrSet = *pAttrsSet;

        for (attrIndex = MIB_ATTR_FIRST_INDEX, i = 0;
                i < MIB_GetTableAttrNum(tableIndex); i++, attrIndex = MIB_ATTR_NEXT_INDEX(attrIndex))
        {
            if (!MIB_IsInAttrSet(pAttrsSet, attrIndex))
                continue;

        }
    }

    if (avcAttrSet != *pAttrsSet)
        *pAttrsSet = avcAttrSet;

    return GOS_OK;
}

static GOS_ERROR_CODE ont_self_loop_detect_alarm_handler(MIB_TABLE_INDEX    tableIndex,
                                                        omci_alm_data_t     alarmData,
                                                        omci_me_instance_t  *pInstanceID,
                                                        BOOL                *pIsUpdated)
{
    mib_alarm_table_t   alarmTable;

    if (!pInstanceID || !pIsUpdated)
        return GOS_ERR_PARAM;

    *pIsUpdated = FALSE;

    // extract instanceID from alarm detail
    *pInstanceID = alarmData.almDetail;

    if (GOS_OK != mib_alarm_table_get(tableIndex, *pInstanceID, &alarmTable))
    {
        OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Get alarm table fail: %s, 0x%x",
            MIB_GetTableName(tableIndex), *pInstanceID);

        return GOS_FAIL;
    }

    // update alarm status if it has being changed
    mib_alarm_table_update(&alarmTable, &alarmData, pIsUpdated);

    if (*pIsUpdated)
    {
        if (GOS_OK != mib_alarm_table_set(tableIndex, *pInstanceID, &alarmTable))
        {
            OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Set alarm table fail: %s, 0x%x",
                MIB_GetTableName(tableIndex), *pInstanceID);

            return GOS_FAIL;
        }
    }

    return GOS_OK;
}

GOS_ERROR_CODE mibTable_init(MIB_TABLE_INDEX tableId)
{
    gMibOntSelfLoopDetectTableInfo.Name = "OntSelfLoopDetect";
    gMibOntSelfLoopDetectTableInfo.ShortName = "SLD";
    gMibOntSelfLoopDetectTableInfo.Desc = "Ont Self Loop Detect";
    gMibOntSelfLoopDetectTableInfo.ClassId = (UINT32)(OMCI_ME_CLASS_ONT_SELF_LOOP_DETECT);
    gMibOntSelfLoopDetectTableInfo.InitType = (UINT32)(OMCI_ME_INIT_TYPE_ONU);
    gMibOntSelfLoopDetectTableInfo.StdType = (UINT32)(OMCI_ME_TYPE_PROPRIETARY);
    gMibOntSelfLoopDetectTableInfo.ActionType = (UINT32)(OMCI_ME_ACTION_SET | OMCI_ME_ACTION_GET);
    gMibOntSelfLoopDetectTableInfo.pAttributes = &(gMibOntSelfLoopDetectAttrInfo[0]);

	gMibOntSelfLoopDetectTableInfo.attrNum = MIB_TABLE_ONTSELFLOOPDETECT_ATTR_NUM;
	gMibOntSelfLoopDetectTableInfo.entrySize = sizeof(MIB_TABLE_ONTSELFLOOPDETECT_T);
	gMibOntSelfLoopDetectTableInfo.pDefaultRow = &gMibOntSelfLoopDetectDefRow;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Name = "EntityID";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].Name = "EnableLoopDetect";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].Name = "DetectAction";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].Name = "SendingPeriod";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].Name = "BlockTimer";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Name = "OnuUniDetectState";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Name = "OnuUniBlockState";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].Name = "UnBlockReason";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].Name = "UnBlockOnuUni";

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Entity ID";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Enable loop detect";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Detect action";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Sending period";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Block timer";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Onu uni detect state";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Onu uni block state";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "UnBlock reason";
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "UnBlock onu uni";

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_WRITE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_WRITE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_WRITE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_WRITE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;

    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ENABLELOOPDETECT_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_DETECTACTION_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_SENDINGPERIOD_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_BLOCKTIMER_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIDETECTSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_ONUUNIBLOCKSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_OPTIONAL;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKREASON_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibOntSelfLoopDetectAttrInfo[MIB_TABLE_ONTSELFLOOPDETECT_UNBLOCKONUUNI_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    memset(&(gMibOntSelfLoopDetectDefRow), 0x00, sizeof(gMibOntSelfLoopDetectDefRow));

    memset(&gMibOntSelfLoopDetectOper, 0x0, sizeof(MIB_TABLE_OPER_T));
	gMibOntSelfLoopDetectOper.meOperDrvCfg = OntSelfLoopDetectCfg;
	gMibOntSelfLoopDetectOper.meOperDump = omci_mib_oper_dump_default_handler;
    gMibOntSelfLoopDetectOper.meOperAlarmHandler = ont_self_loop_detect_alarm_handler;

    MIB_TABLE_ONT_SELFLOOPDETECT_INDEX = tableId;
	MIB_InfoRegister(tableId,&gMibOntSelfLoopDetectTableInfo,&gMibOntSelfLoopDetectOper);
    MIB_RegisterCallback(tableId, NULL, ont_self_loop_detect_avc_cb);

    return GOS_OK;
}
